﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using Microsoft.Popfly.GameCreator.Data;
#if !PHONE
using System.Windows.Browser;
#endif


namespace Microsoft.Popfly.GameCreator.GameEngine
{
#if !PHONE
    [ScriptableType]
#endif
    public partial class PlaySurface : UserControl
    {
        private Game m_game;
        private bool m_showDebugCollisionEdges;

        //We have to wait till game is loaded before we can mute ... so store it as a private variable for now.
        private bool m_mute;
        public PlaySurface(bool mute)
            : this()
        {
            m_mute = mute;
        }

        public PlaySurface()
        {
            InitializeComponent();
            Console.SilverlightConsole = ActiveSilverlightConsole;
#if !PHONE
            HtmlPage.RegisterScriptableObject("PlaySurface", this);
#endif

            App.Current.Host.Content.Resized += new EventHandler(Content_Resized);

            Load("default.game", "resources.xaml");
        }

        void Content_Resized(object sender, EventArgs e)
        {
            var content = App.Current.Host.Content;
            Resize(content.ActualWidth, content.ActualHeight);
        }

#if !PHONE
        [ScriptableMember]
#endif
        public event EventHandler<GamePerformanceEventArgs> GamePerformanceDataUpdated;
#if !PHONE
        [ScriptableMember]
#endif
        public event EventHandler ConsoleShown;
#if !PHONE
        [ScriptableMember]
#endif
        public event EventHandler ConsoleHidden;

#if !PHONE
        [ScriptableMember]
#endif
        public void ChangeScene(int index)
        {
            if (index < 0 || index >= m_game.m_gameInfo.Scenes.Count)
            {
                return;
            }
            m_game.ChangeScene(
                    m_game.m_gameInfo.Scenes.getIndexedValue(index).Name
                );
        }
#if !PHONE
        [ScriptableMember]
#endif
        public bool ShowDebugCollisionEdges
        {
            get
            {
                return m_showDebugCollisionEdges;
            }
            set
            {
                m_showDebugCollisionEdges = value;
                m_game.ShowDebugCollisionEdges = value;
            }
        }

#if !PHONE
        [ScriptableMember]
#endif
        public bool UseConsole
        {
            get
            {
                return ActiveSilverlightConsole.UseConsole;
            }
            set
            {
                ActiveSilverlightConsole.UseConsole = value;
            }
        }

#if !PHONE
        [ScriptableMember]
#endif
        public double ConsoleWidth
        {
            get
            {
                return ActiveSilverlightConsole.Width;
            }
            set
            {
                ActiveSilverlightConsole.Width = value;
                this.Content_Resized(null, null);
            }
        }

#if !PHONE
        [ScriptableMember]
#endif
        public void ShowConsole()
        {
            ActiveSilverlightConsole.Show();
        }

#if !PHONE
        [ScriptableMember]
#endif
        public void HideConsole()
        {
            ActiveSilverlightConsole.Hide();
        }


        public void Resize(double width, double height)
        {
            this.Width = width;
            this.Height = height;

            ActiveSilverlightConsole.Height = height;

            BackgroundCanvas.Width = this.Width - ((ActiveSilverlightConsole.Visibility == Visibility.Visible) ? ActiveSilverlightConsole.Width : 0);
            BackgroundCanvas.Height = Math.Max(this.Height - 22, 23);


            if (m_game != null)
            {
                m_game.FitSceneToCanvas();
            }

            runtimeBar.Width = this.Width - ((ActiveSilverlightConsole.Visibility == Visibility.Visible) ? ActiveSilverlightConsole.Width : 0);
        }

#if !PHONE
        [ScriptableMember]
#endif
        public void Load(string gameXml, string resourcesXml, int initialScene)
        {
            Load(gameXml, resourcesXml);
            ChangeScene(initialScene);
        }
#if !PHONE
        [ScriptableMember]
#endif
        public void Load(string gameXml, string resourcesXml)
        {
            XmlReader gameXamlReader, resourcesReader;

            gameXamlReader = XmlReader.Create(gameXml);
            resourcesReader = XmlReader.Create(resourcesXml);

            GameInfo gameInfo = (GameInfo)GameXamlDeserializer.Deserialize(gameXamlReader, typeof(GameInfo));
            gameXamlReader.Close();

            Resources resources = (Resources)GameXamlDeserializer.Deserialize(resourcesReader, typeof(Resources));
            resourcesReader.Close();

            LayoutRoot.Children.Clear();
            OverlayRoot.Children.Clear();

            if (m_game != null)
            {
                m_game.GamePerformanceDataUpdated -= GameEngineGamePerformanceDataUpdated;
                m_game.Dispose();
            }

            m_game = new Game(gameInfo, resources, this, LayoutRoot, OverlayRoot, runtimeBar, ResizeToFitRoot, false);
            m_game.GamePerformanceDataUpdated += GameEngineGamePerformanceDataUpdated;
            m_game.ShowDebugCollisionEdges = ShowDebugCollisionEdges;

            runtimeBar.Game = m_game;

            runtimeBar.mute = m_mute;

            // m_game.Start(firstState, LayoutRoot);
        }

        void GameEngineGamePerformanceDataUpdated(object sender, GamePerformanceEventArgs e)
        {
            if (GamePerformanceDataUpdated != null)
                GamePerformanceDataUpdated(sender, e);
        }


        private void runtimeBar_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            runtimeBar.Resize(e.NewSize.Width);
        }

        private void ActiveSilverlightConsole_ConsoleHidden(object sender, EventArgs e)
        {
            Content_Resized(null, null);
            if (ConsoleHidden != null)
            {
                ConsoleHidden.Invoke(ActiveSilverlightConsole, null);
            }
        }

        private void ActiveSilverlightConsole_ConsoleShown(object sender, EventArgs e)
        {
            Content_Resized(null, null);
            if (ConsoleShown != null)
            {
                ConsoleShown.Invoke(ActiveSilverlightConsole, null);
            }
        }
    }
}
